package com.bbex.service.impl;

import java.io.StringWriter;
import java.time.LocalDateTime;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import javax.annotation.Resource;

import com.bbex.entity.EntMessage;
import com.bbex.mapper.EntMessageDao;
import com.bbex.util.NumberUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSON;
import com.bbex.config.FreemarkConfig;
import com.bbex.constant.Constants;
import com.bbex.disruptor.DisruptorData;
import com.bbex.disruptor.DisruptorManager;
import com.bbex.entity.MobileSendLog;
import com.bbex.exception.PlatException;
import com.bbex.service.SmsMessageService;
import com.bbex.util.ChuangLanSmsUtil;
import com.bbex.util.SnowFlake;
import com.bbex.entity.SmsSendResponse;
import com.bbex.entity.SmsSendRequest;
import freemarker.core.ParseException;
import freemarker.template.MalformedTemplateNameException;
import freemarker.template.Template;
import freemarker.template.TemplateNotFoundException;

@Service("smsMessageService")
public class SmsMessageServiceImpl implements SmsMessageService {
    public static final String charset = "utf-8";
    private static Logger logger = LoggerFactory.getLogger(SmsMessageServiceImpl.class);

    @Resource(name = "stringRedisTemplate")
    ValueOperations<String, String> valOpsStr;

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    //产品名称:云通信短信API产品,开发者无需替换
    static final String product = "Dysmsapi";
    //产品域名,开发者无需替换
    static final String domain = "dysmsapi.aliyuncs.com";

    // TODO 此处需要替换成开发者自己的AK(在阿里云访问控制台寻找)
  /*  static final String accessKeyId = "LTAIpQPdWb7bMNJg";
    static final String accessKeySecret = "4m5gdjhdH4WW6hsUFBBMJmeP8vq4NW";
    static final String signName = "ECO";
	
    @Value("${access.keyId.conf}")
    private String accessKeyIdConf = accessKeyId ;
    
    @Value("${access.keySecret.conf}")
    private String accessKeySecretConf = accessKeySecret ;
    
    @Value("${access.signName}")
    private String signNameConf = signName ;*/

    @Autowired
    private EntMessageDao entMessageDao;
    
    @Value("${smsSendMod:0}")
    private Integer sendMod ;
    @Value("${accessKey}")
    private String account ;
    @Value("${accessSecret}")
    private String password ;

    public void smsSend(String mobile, String report, Integer type) {

        // 用户平台API账号(非登录账号,示例:N1234567)
        //public static String account = "N3046036";
        // 用户平台API密码(非登录密码)
        //public static String password = "hMkHQ1vWzE7b46";

        //请求地址请登录253云通讯自助通平台查看或者询问您的商务负责人获取
        String smsSingleRequestServerUrl = "http://smssh1.253.com/msg/send/json";
        //4验证码存redis
        String redisTemplatKey = "redis:sms:templat:" + type;
        EntMessage mobileTemplate = (EntMessage) redisTemplate.opsForValue().get(redisTemplatKey);
        if (mobileTemplate == null) {
            mobileTemplate = entMessageDao.findByType(type);
            redisTemplate.opsForValue().set(redisTemplatKey, mobileTemplate, 24 * 3600, TimeUnit.SECONDS);
        }
        if (mobileTemplate == null) {
            throw new PlatException(Constants.MESSAGE_TEMPLATE_NULL_ERROR, "短信不支持的模板");
        }
        try {
            String code = NumberUtils.getRandomNumber(6);
            //将短信中的code部分替换成6位验证码
            mobileTemplate.setContent(mobileTemplate.getContent().replace("${code}", code));
            //短信内容
            String msg = mobileTemplate.getContent();
            //状态报告
            //String report= "true";
            SmsSendRequest smsSingleRequest = new SmsSendRequest(account, password, msg, mobile,report);
            //设置请求参数
            String requestJson = JSON.toJSONString(smsSingleRequest);
            //发送请求
            String response = ChuangLanSmsUtil.sendSmsByPost(smsSingleRequestServerUrl, requestJson);
            //成功返回参数
            SmsSendResponse smsSingleResponse = JSON.parseObject(response, SmsSendResponse.class);

            //记录日志
            String id = SnowFlake.createSnowFlake().nextIdString();
            MobileSendLog mobileSendLog = new MobileSendLog();
            mobileSendLog.setId(id);
            mobileSendLog.setDelFlag("0");
            mobileSendLog.setContent(mobileTemplate.getContent());
            mobileSendLog.setSubject("发送手机号短信" + mobileTemplate.getTitle());
            mobileSendLog.setMobile(mobile);
            mobileSendLog.setCreateDate(LocalDateTime.now());
            DisruptorManager.instance().runConfig();
            DisruptorData data = new DisruptorData();
            data.setType(4);
            data.setMobileSendLog(mobileSendLog);
            if ("0".equals(smsSingleResponse.getCode()) && smsSingleResponse.getCode() != null ) {
                mobileSendLog.setStatus("0");
                DisruptorManager.instance().publishData(data);
                String redisKey = new StringBuffer("redis-sms:").append(mobileTemplate.getMsgtype()).append(":" + mobile).toString();
                valOpsStr.set(redisKey, code, 120, TimeUnit.SECONDS);
            } else {
                mobileSendLog.setStatus("1");
                DisruptorManager.instance().publishData(data);
                logger.error("发送短信失败， mobile = {}", mobile);
                throw new PlatException(Constants.GLOBAL_ERROR_CODE, smsSingleResponse.getErrorMsg());
            }
            System.out.println("response  toString is :" + smsSingleResponse);
        } catch (Exception e) {
            logger.error("发送短信失败， mobile = {},aliyun调用失败", mobile);
            throw new PlatException(Constants.GLOBAL_ERROR_CODE, "短信发送失败");
        }
    }

    @Override
    public boolean validSmsCode(String mobile, Integer type) {
        return false;
    }

    public void sendSms(String mobile, String templateCode, String outId) {
        //4验证码存redis
        /*String redisTemplatKey = "redis:sms:templat:" + templateCode;
        MobileTemplate mobileTemplate = (MobileTemplate) redisTemplate.opsForValue().get(redisTemplatKey);
        if (mobileTemplate == null) {
            mobileTemplate = mobileTemplateDao.findByCode(templateCode);
            redisTemplate.opsForValue().set(redisTemplatKey, mobileTemplate, 24 * 3600, TimeUnit.SECONDS);
        }
        if (mobileTemplate == null) {
            throw new PlatException(Constants.MESSAGE_TEMPLATE_NULL_ERROR, "短信不支持的模板");
        }
        try {
            String code = NumberUtils.getRandomNumber(6);
            //替换自动生成的参数
            if (StringUtils.isNotBlank(outId) && StringHelp.regexMatcher("\\d+", outId)) {
                code = outId;
            }
            //初始化acsClient,暂不支持region化
            IClientProfile profile = DefaultProfile.getProfile("cn-hangzhou", mobileTemplate.getAccessKey(), mobileTemplate.getAccessSecret());
            DefaultProfile.addEndpoint("cn-hangzhou", "cn-hangzhou", product, domain);
            IAcsClient acsClient = new DefaultAcsClient(profile);
            //组装请求对象-具体描述见控制台-文档部分内容
            SendSmsRequest request = new SendSmsRequest();
            request.setConnectTimeout(10000);
            request.setReadTimeout(10000);
            //必填:待发送手机号
            request.setPhoneNumbers(mobile);
            //必填:短信签名-可在短信控制台中找到
            request.setSignName(mobileTemplate.getSignName());
            //必填:短信模板-可在短信控制台中找到
            //SMS_136700099
            request.setTemplateCode(mobileTemplate.getTemplateCode());
            //可选:模板中的变量替换JSON串,如模板内容为"亲爱的${name},您的验证码为${code}"时,此处的值为
            Map<String, Object> params = new HashMap<>();
            params.put("code", code);
            String templateParam = getContent(mobileTemplate.getTemplateCode(), mobileTemplate.getTemplateParam(), params);
            //"{\"code\":"+code+"}"
            request.setTemplateParam(templateParam);
            //选填-上行短信扩展码(无特殊需求用户请忽略此字段)
            //request.setSmsUpExtendCode("90997");
            //可选:outId为提供给业务方扩展字段,最终在短信回执消息中将此值带回给调用者
            if (StringUtils.isNotBlank(mobileTemplate.getWorkSign())) {
                //"yourOutId"
                request.setOutId(mobileTemplate.getWorkSign());
            }
            //记录日志
            SendSmsResponse sendSmsResponse = acsClient.getAcsResponse(request);
            String id = SnowFlake.createSnowFlake().nextIdString();
            MobileSendLog mobileSendLog = new MobileSendLog();
            mobileSendLog.setId(id);
            mobileSendLog.setDelFlag("0");
            mobileSendLog.setBusinessType(mobileTemplate.getTemplateCode());
            mobileSendLog.setTemplateId(templateCode);
            mobileSendLog.setContent(templateParam);
            mobileSendLog.setSubject("发送手机号短信" + mobileTemplate.getTemplateCode());
            mobileSendLog.setMobile(mobile);
            mobileSendLog.setCreateDate(LocalDateTime.now());
            long expireTime = SercurityConstant.REDIS_EXPIRE_TIME_HALF_HOUR;
            if (mobileTemplate.getTimeOut() != null) {
                expireTime = mobileTemplate.getTimeOut();
            }
            mobileSendLog.setExpireTime(LocalDateTime.now().plusSeconds(expireTime));
            DisruptorManager.instance().runConfig();
            DisruptorData data = new DisruptorData();
            data.setType(4);
            data.setMobileSendLog(mobileSendLog);
            if (sendSmsResponse.getCode() != null && sendSmsResponse.getCode().equals("OK")) {
                mobileSendLog.setStatus("0");
                DisruptorManager.instance().publishData(data);
                String redisKey = new StringBuffer("redis-sms:").append(mobileTemplate.getTemplateCode()).append(":" + mobile).toString();
                valOpsStr.set(redisKey, code, mobileTemplate.getTimeOut(), TimeUnit.SECONDS);
            } else {
                mobileSendLog.setStatus("1");
                DisruptorManager.instance().publishData(data);
                logger.error("发送短信失败， mobile = {}", mobile);
                throw new PlatException(Constants.GLOBAL_ERROR_CODE, sendSmsResponse.getMessage());
            }
        } catch (ClientException e) {
            logger.error("发送短信失败， mobile = {},aliyun调用失败", mobile);
            throw new PlatException(Constants.GLOBAL_ERROR_CODE, "短信发送失败");
        }*/
    }

    private static String getContent(String templateName, String template, Map<String, Object> params) {
        try {
            StringWriter out = new StringWriter(1024);
            FreemarkConfig.newInstance().getStringTemplateLoader().putTemplate(templateName, template);
            Template temp = FreemarkConfig.newInstance().getConfiguration().getTemplate(templateName, "utf-8");
            temp.process(params, out);
            return out.toString();
        } catch (TemplateNotFoundException e) {
            throw new PlatException(Constants.COMMON_ERROR_CODE, "freemark模板没有找到");
        } catch (MalformedTemplateNameException e) {
            throw new PlatException(Constants.COMMON_ERROR_CODE, "freemark邮件模板异常");
        } catch (ParseException e) {
            throw new PlatException(Constants.COMMON_ERROR_CODE, "freemark解析邮件模板异常");
        } catch (Exception e) {
            throw new PlatException(Constants.COMMON_ERROR_CODE, "freemark格式化邮件模板异常");
        }
    }

    @Override
    public void sendSms(String countryCode, String mobile, String template, String outId) throws PlatException {
        /*if (StringUtils.isBlank(countryCode)||"86".equalsIgnoreCase(countryCode)||86==Integer.parseInt(countryCode)) {
        	if(sendMod == 0){
        		sendSms(mobile, template, outId);
        	}else {
        		sendSmsByCountryCode("0086",mobile, template+"_86", outId);
        	}
        }else {
        	sendSmsByCountryCode(countryCode,mobile, template+"_cl", outId);
        }*/
        //预留其他国家的短信接口
    }

    private void sendSmsByCountryCode(String countryCode,String mobile, String templateCode, String outId) {
    	//4验证码存redis
        /*String redisTemplatKey = "redis:sms:templat:" + templateCode;
        MobileTemplate mobileTemplate = (MobileTemplate) redisTemplate.opsForValue().get(redisTemplatKey);
        if (mobileTemplate == null) {
            mobileTemplate = mobileTemplateDao.findByCode(templateCode);
            redisTemplate.opsForValue().set(redisTemplatKey, mobileTemplate, 24 * 3600, TimeUnit.SECONDS);
        }
        if (mobileTemplate == null) {
            throw new PlatException(Constants.MESSAGE_TEMPLATE_NULL_ERROR, "短信不支持的模板");
        }
        try {
            String code = NumberUtils.getRandomNumber(6);
            //替换自动生成的参数
            if (StringUtils.isNotBlank(outId) && StringHelp.regexMatcher("\\d+", outId)) {
                code = outId;
            }
            Map<String, Object> params = new HashMap<>();
            params.put("code", code);
            String templateParam = getContent(mobileTemplate.getTemplateCode(), mobileTemplate.getTemplateParam(), params);
            //发送国际短信
            SmsSendRequest ssrq =  new SmsSendRequest(mobileTemplate.getAccessKey(), mobileTemplate.getAccessSecret(), templateParam, mobile,Integer.parseInt(countryCode)+mobile,"true");
            String requestJson = JSON.toJSONString(ssrq);
            String response = ChuangLanSmsUtil.sendSmsByPost(mobileTemplate.getWorkSign(), requestJson);
            SmsSendResponse smsSingleResponse = JSON.parseObject(response, SmsSendResponse.class);
            if(logger.isDebugEnabled()) {
            	logger.debug("发送国际短信countryCode:{},mobile:{},返回发送结果result:{}",countryCode,mobile,smsSingleResponse);
            }
            String id = SnowFlake.createSnowFlake().nextIdString();
            MobileSendLog mobileSendLog = new MobileSendLog();
            mobileSendLog.setId(id);
            mobileSendLog.setDelFlag("0");
            mobileSendLog.setBusinessType(mobileTemplate.getTemplateCode());
            mobileSendLog.setTemplateId(templateCode);
            mobileSendLog.setContent(templateParam);
            mobileSendLog.setSubject("发送手机号短信" + mobileTemplate.getTemplateCode());
            mobileSendLog.setMobile(mobile);
            mobileSendLog.setCreateDate(LocalDateTime.now());
            long expireTime = SercurityConstant.REDIS_EXPIRE_TIME_HALF_HOUR;
            if (mobileTemplate.getTimeOut() != null) {
                expireTime = mobileTemplate.getTimeOut();
            }
            mobileSendLog.setExpireTime(LocalDateTime.now().plusSeconds(expireTime));
            DisruptorManager.instance().runConfig();
            DisruptorData data = new DisruptorData();
            data.setType(4);
            data.setMobileSendLog(mobileSendLog);
            if (smsSingleResponse.getCode() != null && smsSingleResponse.getCode().equals("0")) {
                mobileSendLog.setStatus("0");
                DisruptorManager.instance().publishData(data);
                String redisKey = new StringBuffer("redis-sms:").append(mobileTemplate.getTemplateCode()).append(":" + mobile).toString();
                valOpsStr.set(redisKey, code, mobileTemplate.getTimeOut(), TimeUnit.SECONDS);
            } else {
                mobileSendLog.setStatus("1");
                DisruptorManager.instance().publishData(data);
                logger.error("发送短信失败， mobile = {}", mobile);
                throw new PlatException(Constants.GLOBAL_ERROR_CODE, smsSingleResponse.getErrorMsg());
            }
        } catch (Exception e) {
            logger.error("发送短信失败， mobile = {},创蓝国际短信,调用失败", mobile);
            throw new PlatException(Constants.GLOBAL_ERROR_CODE, "短信发送失败");
        }*/
	}

    @Override
    public boolean validSmsCode(String mobile, String templateCode, String code) throws PlatException {
        return false;
    }

    @Override
    public boolean validSmsCode(String mobile, Integer type, String code) {
        return validSmsCodeByCountryCode(mobile,type,code);
    }
    
    public boolean validSmsCodeByCountryCode(String mobile, Integer type, String code) {
        String redisTemplatKey = "redis:sms:templat:" + type;
        EntMessage mobileTemplate = (EntMessage) redisTemplate.opsForValue().get(redisTemplatKey);
        if (mobileTemplate == null) {
            mobileTemplate = entMessageDao.findByType(type);
            redisTemplate.opsForValue().set(redisTemplatKey, mobileTemplate, 24 * 3600, TimeUnit.SECONDS);
        }
        if (mobileTemplate == null) {
            throw new PlatException(Constants.MESSAGE_TEMPLATE_NULL_ERROR, "短信不支持的模板");
        }
        String redisKey = new StringBuffer("redis-sms:").append(mobileTemplate.getMsgtype()).append(":" + mobile).toString();
        if (!valOpsStr.getOperations().hasKey(redisKey)) {
            throw new PlatException(Constants.COMMON_ERROR_CODE, "请重新获取验证码");
        }
        String redisCode = valOpsStr.get(redisKey);
        if (StringUtils.isBlank(code)) {
            throw new PlatException(Constants.COMMON_ERROR_CODE, "验证码已失效");
        }
        if (!redisCode.equalsIgnoreCase(code)) {
            throw new PlatException(Constants.COMMON_ERROR_CODE, "验证码错误");
        }
        valOpsStr.getOperations().delete(redisKey);
        return true;
    }

    @Override
    public boolean validSmsCode(String countryCode, String mobile, String templateCode, String code) throws PlatException {
        return false;
    }
}
